package com.example.lib_router_compiler.ksp.compiler

import com.example.lib_router_anntation.RouterPath
import com.example.lib_router_anntation.RouterService
import com.example.lib_router_anntation.RouterServiceImpl
import com.google.devtools.ksp.processing.*
import com.google.devtools.ksp.symbol.KSAnnotated
import com.google.devtools.ksp.symbol.KSClassDeclaration
import com.squareup.kotlinpoet.ksp.KotlinPoetKspPreview
import com.squareup.kotlinpoet.ksp.toClassName

/**
 * @author wengcj
 * @date 2023/1/28 17:43
 */
class GenProvider : SymbolProcessorProvider {
    override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor {
        return GenProcessor(environment.codeGenerator, environment.logger, environment.options)
    }

    inner class GenProcessor(
        private val codeGenerator: CodeGenerator,
        private val logger: KSPLogger,
        private val options: Map<String, String>
    ) : SymbolProcessor {
        private var packageName = ""
        private var className = ""
        private var moduleName = ""

        private val routerPathMap = mutableMapOf<String, String>()
        private val routerServiceMap = mutableMapOf<String, String>()
        private val routerServiceImplMap = mutableMapOf<String, RouterServiceImplInfo>()

        private var codeGenerated = false

        override fun process(resolver: Resolver): List<KSAnnotated> {
            if (codeGenerated) {
                return emptyList()
            }

            logger.warn("GenProcessor ----------------------start--------------------")
            val start = System.currentTimeMillis()
            moduleName = options["moduleName"].toString()
            val testModuleName = moduleName(resolver)
            className = getModuleName(moduleName ?: "testClassName")
            packageName = DEFAULT_PACKAGE
            logger.warn("GenProcessor process >>>>>>>> moduleName:$moduleName testModuleName $testModuleName")

            val routerPathSymbol =
                resolver.getSymbolsWithAnnotation(RouterPath::class.qualifiedName!!)

            val routerServiceSymbol =
                resolver.getSymbolsWithAnnotation(RouterService::class.qualifiedName!!)

            val routerServiceImplSymbol =
                resolver.getSymbolsWithAnnotation(RouterServiceImpl::class.qualifiedName!!)

            val routerPathList = routerPathSymbol
                .filter { it is KSClassDeclaration }
                .map {
                    it as KSClassDeclaration
                }.toList()

            val routerServiceList = routerServiceSymbol
                .filter { it is KSClassDeclaration }
                .map {
                    it as KSClassDeclaration
                }.toList()

            val routerServiceImplList = routerServiceImplSymbol
                .filter { it is KSClassDeclaration }
                .map {
                    it as KSClassDeclaration
                }.toList()
            logger.logging("GenProcessor routerPath $routerPathList ")
            logger.logging("GenProcessor routerServiceList $routerServiceList ")
            logger.logging("GenProcessor routerServiceImplList $routerServiceImplList ")
            if (routerPathList.isNullOrEmpty() && routerServiceList.isNullOrEmpty() && routerServiceImplList.isNullOrEmpty()) return emptyList()

            genFile(resolver,routerPathList, routerServiceList, routerServiceImplList)
            logger.logging("GenProcessor process routerpath $routerPathList ")
            logger.logging("GenProcessor process>>>>>>>> end")
            logger.logging("GenProcessor ----------------------end-----耗时:${(System.currentTimeMillis() - start)}ms---------------")
            codeGenerated = true
            return emptyList()
        }

        @OptIn(KotlinPoetKspPreview::class)
        private fun genFile(
            resolver: Resolver,
            routerPathList: List<KSClassDeclaration>,
            routerServiceList: List<KSClassDeclaration>,
            routerServiceImplList: List<KSClassDeclaration>
        ) {

            //RouterPath注解信息收集
            routerPathList.forEach { kSClassDeclaration ->
                logger.warn("GenProcessor ksClassDeclaration 全类名 ${kSClassDeclaration.toClassName()} ")
                logger.logging("GenProcessor ksClassDeclaration 全路径 ${kSClassDeclaration.location} ")
                logger.logging("GenProcessor ksClassDeclaration qualifiedName ${kSClassDeclaration.qualifiedName?.asString()} ")
                kSClassDeclaration.annotations.forEach { annotation ->
                    if (RouterPath::class.simpleName != annotation.shortName.getShortName()) return@forEach
                    //获取注解的参数
                    val key = annotation.arguments.firstOrNull()?.value.toString()
                    routerPathMap[key] = kSClassDeclaration.toClassName().toString()
                }
            }
            //RouterService注解信息收集
            routerServiceList.forEach { kSClassDeclaration ->
                logger.warn("GenProcessor ksClassDeclaration 全类名 ${kSClassDeclaration.toClassName()} ")
                logger.warn("GenProcessor ksClassDeclaration 全路径 ${kSClassDeclaration.location} ")
                kSClassDeclaration.annotations.forEach { annotation ->
                    if (RouterService::class.simpleName != annotation.shortName.getShortName()) return@forEach

                    //获取注解的参数
                    annotation.arguments.forEach {
                        logger.warn("GenProcessor routerServiceList 注解参数 name ${it.name?.getShortName()} value ${it.value}")
                    }
                    val key = annotation.arguments.firstOrNull()?.value.toString()
                    routerServiceMap[key] = kSClassDeclaration.toClassName().toString()
                }
            }

            //RouterServiceImpl注解信息收集
            routerServiceImplList.forEach { kSClassDeclaration ->
                val simpleName = kSClassDeclaration.simpleName.getShortName()
                logger.warn("GenProcessor ksClassDeclaration simpleName $simpleName ")
                logger.warn("GenProcessor ksClassDeclaration 全类名 ${kSClassDeclaration.toClassName()} ")
                logger.warn("GenProcessor ksClassDeclaration 全路径 ${kSClassDeclaration.location} ")

                logger.warn("GenProcessor kSClassDeclaration.annotations size ${kSClassDeclaration.annotations.toList().size} ")

                kSClassDeclaration.annotations.forEach { annotation ->
                    //获取注解的参数
                    logger.warn("GenProcessor annotation shortName ${annotation.shortName.getShortName()} ")
                    logger.warn("GenProcessor annotation qualifiedName ${RouterServiceImpl::class.simpleName} ")
                    logger.warn("GenProcessor arguments size ${annotation.arguments.size} ")

                    if (RouterServiceImpl::class.simpleName != annotation.shortName.getShortName()) return@forEach

                    val singleton = annotation.arguments.getOrNull(0)?.value as Boolean
                    val identity = annotation.arguments.getOrNull(1)?.value.toString()
                    logger.warn("GenProcessor routerServiceImplList 注解参数 singleton $singleton identity$identity")

                    if (identity.isNullOrEmpty() && !simpleName.endsWith("Impl")) {
                        "@RouterServiceImpl class name must end with Impl!".loge()
                        return@forEach
                    }

                    val realKey = identity.ifEmpty {
                        val index = simpleName.lastIndexOf("Impl")
                        simpleName.substring(0, index)
                    }.toString()
                    routerServiceImplMap[realKey] = RouterServiceImplInfo(
                        kSClassDeclaration.toClassName().toString(),
                        singleton
                    )

                }
            }
            logger.warn("GenProcessor packageName $packageName className $className moduleName $moduleName")
            logger.warn("GenProcessor routerPathMap $routerPathMap ")
            logger.warn("GenProcessor routerServiceMap $routerServiceMap")
            logger.warn("GenProcessor routerServiceImplMap$routerServiceImplMap")
            val file = codeGenerator.createNewFile(
                dependencies = Dependencies.ALL_FILES,
                packageName = packageName,
                fileName = className
            )

            val generator = Generator(
                packageName,
                className,
                routerPathMap,
                routerServiceMap,
                routerServiceImplMap
            )
            val generate = generator.generate()

            file.write(generate.toString().toByteArray())
            file.close()
            //通过下列代码生成文件  会导致编译器重新编译时删除已有文件
//            generate.writeTo(codeGenerator, false)
        }

        private fun String.logn() {
            logger.info(this)
        }

        private fun String.logw() {
            logger.warn(this)
        }

        private fun String.loge() {
            logger.exception(java.lang.IllegalArgumentException(this))
        }

        private fun moduleName(resolver: Resolver): String {
            var moduleName = ""
            val moduleDescriptor = resolver::class.java
                .getDeclaredField("module")
                .apply { isAccessible = true }
                .get(resolver)
            val rawName = moduleDescriptor::class.java
                .getMethod("getName")
                .invoke(moduleDescriptor)
                .toString()
            moduleName = rawName.removeSurrounding("<", ">")
            moduleName = moduleName.substring(0,moduleName.lastIndexOf("_"))
            logger.warn("rawName $rawName")
            logger.warn("moduleName $moduleName")

            return moduleName
        }
    }


}

